package com.example.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
/**
 * Created by IntelliJ IDEA2021.3
 *网络安全配置类
 * @Author: Tenghw
 * @Date: 2022/03/17  23:36
 * @Description:
 */
@Slf4j
@Configuration
@EnableWebSecurity
@SuppressWarnings("all")
@EnableGlobalMethodSecurity(prePostEnabled = true)
//@CrossOrigin(maxAge = 3600,methods = RequestMethod.POST)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //=========================注入BCryptPasswordEncoder============================
    //BCryptPasswordEncoder实现接口PasswordEncoder,BCryptPasswordEncoder是SpringSecurity中的加密类。
//    @Bean
//    public PasswordEncoder passwordEncoder(){
//        return new BCryptPasswordEncoder();
//    }
//    @Autowired
//    PasswordEncoder passwordEncoder;
    //==============================================================================

   //    从 Spring5开始，强制要求密码要加密，如果不想加密，可以使用一个过期的 PasswordEncoder 的实例
   //    NoOpPasswordEncoder，密码不用加密，直接明文形式，不建议用，毕竟不安全。
    //   @Bean
    //    PasswordEncoder passwordEncoder(){
    //        return NoOpPasswordEncoder.getInstance();
    //    }


    //===================PasswordEncoder给密码加密===========================================================
//    @Override
//    public void configure(AuthenticationManagerBuilder auth) throws Exception {
//        //对密码“123”加密
//        String password = passwordEncoder.encode("123");
//        log.info("密码'123'加密后为12345==="+password);
//        auth.inMemoryAuthentication()
//                .withUser("thw").password(password).roles("admin")
//                .and()
//                .withUser("thw1").password(password).roles("user")
//                .and()
//                .withUser("thw2").password(password).roles("temp");
//
//    }
    //==============================================================================

    //HttpSecurity配置用户端请求url的访问权限
    @Override
    public void configure(HttpSecurity httpSecurity) throws Exception {

//    httpSecurity.authorizeRequests()
//                //只有admin角色的用户才能访问路径/login/**——已经登录前提下
//                .antMatchers("/login/**").hasRole("admin")
//                //只有user和temp角色的用户才能访问路径/login/**——已经登录前提下
//                .antMatchers("/login/**").hasAnyRole( "user","temp")
//                //只有admin和user角色的用户才能访问路径/login/**——已经登录前提下
//               .antMatchers("/login/**").access("hasAnyRole('admin','user')")
//               //剩下的其他路径请求验证之后[即账户密码被security认证正确]就可以访问
//                .anyRequest().authenticated()
//
//                .and()
//                 //开启表单登录
//                .formLogin()
//                // 登录处理的url,当发现是/login时认为是登录，必须和前端表单提交action的地址一样,不写默认.loginProcessingUrl("/login")
//                .loginProcessingUrl("/login")
//                // 自定义的登录页面，如果不写会使用默认的登陆页面”localhost:8080/login“,即我请求url“localhost:8080”被自动重定向到的”localhost:8080/login“。
////                .loginPage("/e/a/n")
//                //定义登录时，用户名的 key，默认为 username
//                .usernameParameter("username")
//                //定义登录时，用户名的 key，默认为 password
//                .passwordParameter("password")
////            //登录成功后跳转到static静态资源中的main.html,也可以跳转到Controller的某个请求url中。
////            .successForwardUrl("Main.html");
//            //=================================================================================
//
//            //=========successHandler登陆成功的处理（用于前后端分离时，直接返回json登录成功=============
////                .successHandler(new AuthenticationSuccessHandler() {
////                    @Override
////                    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
////                        response.setContentType("application/json;charset=utf-8");
////                        PrintWriter pw = response.getWriter();
////                        Map<String, Object> map = new HashMap<String, Object>();
////                        map.put("status", 200);
////                        map.put("msg", authentication.getPrincipal());//authentication.getPrincipal()存放登陆成功后的用户信息
////                        pw.write(new ObjectMapper().writeValueAsString(map));
////                        pw.flush();
////                        pw.close();
////                    }
////                })
//            //=====================================================================================
//
//            //========================登录失败=======================================================
//            .failureHandler(new AuthenticationFailureHandler() {
//                @Override
//                public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
//                    response.setContentType("application/json;charset=utf-8");
//                    PrintWriter pw = response.getWriter();
//                    Map<String, Object> map = new HashMap<String, Object>();
//                    map.put("status", 401);
//                    if (exception instanceof LockedException) {
//                        map.put("msg", "账户被锁定，登陆失败！");
//                    } else if (exception instanceof BadCredentialsException) {
//                        map.put("msg", "账户或者密码错误，登陆失败！");
//                    } else if (exception instanceof DisabledException) {
//                        map.put("msg", "账户被禁用，登陆失败！");
//                    } else if (exception instanceof AccountExpiredException) {
//                        map.put("msg", "账户已过期，登陆失败！");
//                    } else if (exception instanceof CredentialsExpiredException) {
//                        map.put("msg", "密码已过期，登陆失败！");
//                    } else {
//                        map.put("msg", "登陆失败！");
//                    }
//                    pw.write(new ObjectMapper().writeValueAsString(map));
//                    pw.flush();
//                    pw.close();
//                        }
//                    })
//                //==============================================================================
//                //放开和登陆有关的接口
//                .permitAll();
               //===================================================================================

               //关闭 csrf 保护,否则页面无法访问;csrf跨站请求伪造,CSRF默认支持的方法： GET|HEAD|TRACE|OPTIONS，不支持POST。可以在security配置中禁用掉它。
                httpSecurity.csrf().disable();
                super.configure(httpSecurity);
              //===================================================================================

    }


}
